"""命令行入口，串联 ETF 风控与量化分析 agent."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Optional

# 支持直接运行 python main.py
# 将项目根目录添加到 sys.path，以便使用绝对导入
_project_root = Path(__file__).parent.parent
if str(_project_root) not in sys.path:
    sys.path.insert(0, str(_project_root))

from src.agents import TaskAgentRunner, TaskAgentRunnerConfig
from src.agents.base import AgentConfig
from src.utils import now_shanghai
from src.pipelines.prediction_inputs import (
    PredictionInputsError,
    build_prediction_auto_inputs,
)
from src.utils import GLOBAL_DATA_STORE


def _now_iso() -> str:
    return now_shanghai().isoformat(timespec="seconds")


def _write_output(content: str, output: Optional[str]) -> None:
    if not output:
        return
    path = Path(output)
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")


def run_risk(args: argparse.Namespace) -> str:
    runner = TaskAgentRunner(config=TaskAgentRunnerConfig(agent_config=AgentConfig()))
    report = runner.run_risk_control(args.fund, args.current_time)
    _write_output(report, args.output)
    print(report)
    return report


def run_quant(args: argparse.Namespace, risk_report: Optional[str] = None) -> str:
    runner = TaskAgentRunner(config=TaskAgentRunnerConfig(agent_config=AgentConfig()))
    report = runner.run_quant_analysis(args.fund, args.current_time, risk_report_summary=risk_report)
    _write_output(report, args.output)
    print(report)
    return report


def run_prediction(args: argparse.Namespace, quant_report: str, risk_report: str) -> str:
    runner = TaskAgentRunner(config=TaskAgentRunnerConfig(agent_config=AgentConfig()))
    report = runner.run_prediction(
        fund=args.fund,
        current_time=args.current_time,
        position=args.position,
        latest_quote=args.latest_quote,
        quant_summary=quant_report,
        risk_summary=risk_report,
        technical_snapshot=args.technical_snapshot,
        model_name=args.model_name,
    )
    _write_output(report, args.output)
    print(report)
    return report


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        description="基于 LangChain 的 ETF 风控与量化分析 agent",
    )
    parser.add_argument("--current-time", default=_now_iso(), help="当前时间，默认使用本地时间 ISO 格式")
    subparsers = parser.add_subparsers(dest="command", required=True)

    risk_parser = subparsers.add_parser("risk", help="生成风险控制报告")
    risk_parser.add_argument("--fund", required=True, help="ETF 基金代码，例如 159919")
    risk_parser.add_argument("--output", help="将报告写入指定路径")
    risk_parser.set_defaults(func=run_risk)

    quant_parser = subparsers.add_parser("quant", help="生成量化分析报告")
    quant_parser.add_argument("--fund", required=True, help="ETF 基金代码")
    quant_parser.add_argument("--output", help="将报告写入指定路径")
    quant_parser.add_argument(
        "--risk-report",
        help="风险控制报告文本。若未提供，则尝试使用此前缓存的风险指标摘要。",
    )
    quant_parser.set_defaults(func=run_quant)

    full_parser = subparsers.add_parser("full", help="顺序运行风险控制与量化分析")
    full_parser.add_argument("--fund", required=True, help="ETF 基金代码")
    full_parser.add_argument("--output-dir", help="报告输出目录")
    full_parser.set_defaults(func=None)

    predict_parser = subparsers.add_parser("predict", help="生成预测与交易建议报告")
    predict_parser.add_argument("--fund", required=True, help="ETF 基金代码")
    predict_parser.add_argument("--position", required=True, help="当前持仓描述")
    predict_parser.add_argument("--latest-quote", required=True, help="最新价格与净值摘要")
    predict_parser.add_argument("--technical-snapshot", required=True, help="当前技术指标概况")
    predict_parser.add_argument("--model-name", required=True, help="当前使用的大模型名称")
    predict_parser.add_argument("--risk-report", required=True, help="风险控制报告文本")
    predict_parser.add_argument("--quant-report", required=True, help="量化分析报告文本")
    predict_parser.add_argument("--output", help="将报告写入指定路径")
    predict_parser.set_defaults(func=None)

    parser.add_argument(
        "--show-cache",
        action="store_true",
        help="显示当前缓存的历史数据摘要（调试用途）",
    )

    return parser


def main() -> None:
    parser = build_parser()
    args = parser.parse_args()

    if args.command == "full":
        risk_output = (
            str(Path(args.output_dir) / "risk_report.md") if args.output_dir else None
        )
        setattr(args, "output", risk_output)
        risk_report = run_risk(args)
        quant_args = argparse.Namespace(
            fund=args.fund,
            current_time=args.current_time,
            output=str(Path(args.output_dir) / "quant_report.md") if args.output_dir else None,
            risk_report=risk_report,
        )
        quant_report = run_quant(quant_args, risk_report)
        try:
            auto_inputs = build_prediction_auto_inputs(args.fund)
        except PredictionInputsError as error:
            print(f"构建预测输入失败：{error}", file=sys.stderr)
            if args.show_cache:
                _print_cache()
            return

        prediction_args = argparse.Namespace(
            fund=args.fund,
            current_time=args.current_time,
            position=auto_inputs.position,
            latest_quote=auto_inputs.latest_quote,
            technical_snapshot=auto_inputs.technical_snapshot,
            model_name=auto_inputs.model_name,
            output=str(Path(args.output_dir) / "prediction_report.md") if args.output_dir else None,
        )
        run_prediction(
            prediction_args,
            quant_report=quant_report,
            risk_report=risk_report,
        )
        if args.show_cache:
            _print_cache()
        return

    if args.command == "predict":
        risk_report = args.risk_report
        quant_report = args.quant_report
        run_prediction(args, quant_report=quant_report, risk_report=risk_report)
        if args.show_cache:
            _print_cache()
        return

    risk_report_text = None
    if args.command == "quant":
        risk_report_text = args.risk_report

    result = args.func(args, risk_report_text) if args.command == "quant" else args.func(args)

    if args.show_cache:
        _print_cache()

    return result


def _print_cache() -> None:
    datasets = {
        symbol: {
            "count": dataset.count,
            "start": dataset.start.isoformat(),
            "end": dataset.end.isoformat(),
        }
        for symbol, dataset in GLOBAL_DATA_STORE.datasets.items()
    }
    print("缓存的 ETF 历史数据：")
    print(json.dumps(datasets, ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()

